package com.hyt.it.ogt.kq.main.controller.bm;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.exception.annotation.ThrowsAdvice;
import com.hyt.it.ogt.cj.model.vo.ProjectCollectInfoVo;
import com.hyt.it.ogt.kq.common.bm.progress.ImportStudentLockKeyCreator;
import com.hyt.it.ogt.kq.common.bm.swagger.BmApiVersionConstant;
import com.hyt.it.ogt.kq.common.bm.utils.Constant;
import com.hyt.it.ogt.kq.common.bm.utils.ThreadLocalProvider;
import com.hyt.it.ogt.kq.common.gov.config.swagger.ApiVersionConstant;
import com.hyt.it.ogt.kq.common.gov.progress.BatchImportFileLockKeyCreator;
import com.hyt.it.ogt.kq.common.utils.KqStringUtils;
import com.hyt.it.ogt.kq.main.controller.base.BaseController;
import com.hyt.it.ogt.kq.service.bm.feign.file.FileClient;
import com.hyt.it.ogt.kq.service.bm.model.dto.FjzfSyncStudentDto;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubject;
import com.hyt.it.ogt.kq.service.bm.model.param.BatchImportFileParam;
import com.hyt.it.ogt.kq.service.bm.model.param.BatchImportManualParam;
import com.hyt.it.ogt.kq.service.bm.model.vo.*;
import com.hyt.it.ogt.kq.service.bm.service.IStudentInfoService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentSubjectService;
import com.hyt.log.annotation.Log;
import com.hyt.loginfo.model.User;
import com.hyt.model.PageParam;
import com.hyt.progress.creator.anno.ProgressAnno;
import com.hyt.progress.service.ProgressManager;
import com.hyt.resubmit.annotation.AvoidReSubmit;
import com.hyt.swagger.ApiVersion;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 考生基础信息
 * </p>
 *
 * @author wangt
 * @since 2020-05-15
 */
@Slf4j
@RestController
@Api(tags = "8.考生基础信息接口", value = "考生基础信息接口")
@ApiSort(value = 8)
@RequestMapping("/bm/student-info")
public class StudentInfoController extends BaseController {

    @Resource
    private IStudentInfoService iStudentInfoService;
    @Resource
    private IStudentSubjectService iStudentSubjectService;
    @Resource
    private FileClient fileClient;

    @ApiOperation(value = "8.1.1 添加考生基础信息(保存，下一步)", notes = "(保存，下一步)14001:成功；15001：添加考生基础信息数据失败")
    @ApiOperationSort(value = 1)
    @ApiVersion(group = {ApiVersionConstant.V2_4_10})
    @AvoidReSubmit
    @ThrowsAdvice(code = 31081108, print = "添加考生基础信息异常")
    @Log(module = "考生基础信息管理", business = "添加考生基础信息")
    @PostMapping(value = "/add")
    public ApiResponse<Object> add(@RequestBody StudentInfoListVo studentInfoListVo) {
        // 判断手机+邮箱是否重复
        iStudentInfoService.isAgainData(studentInfoListVo);
        return iStudentInfoService.addStudentInfoData(studentInfoListVo);
    }

    @ApiOperation(value = "8.1.2 编辑考生基础信息数据", notes = "14001:成功；15002：编辑考生基础信息数据失败")
    @ApiOperationSort(value = 2)
    @ThrowsAdvice(code = 31191602, print = "更新失败，请联系管理员")
    @Log(module = "考生基础信息管理", business = "编辑考生基础信息数据")
    @RequestMapping(value = "/update", method = RequestMethod.PUT)
    public ApiResponse<Object> update(@RequestBody StudentInfoListVo studentInfoListVo) {
        iStudentInfoService.checkData(studentInfoListVo);
        return iStudentInfoService.updateStudentInfoData(studentInfoListVo);
    }

    @ApiOperation(value = "8.1.3 查看考生基础信息数据", notes = "14001:成功；15003：未查找到考生基础信息数据")
    @ApiOperationSort(value = 3)
    @ThrowsAdvice(code = 31010199, print = "未查找到考生基础信息数据")
    @GetMapping(value = "/query/{studentId}/{projectId}")
    public ApiResponse<Object> query(@PathVariable String studentId, @PathVariable String projectId) throws Exception {
        return iStudentInfoService.queryStudentBaseInfo(studentId, projectId);
    }

    @Deprecated
    @ApiOperation(value = "8.1.4 管理端：查询考生列表", notes = "14001:成功", response = StudentVo.class)
    @ApiOperationSort(value = 4)
    @ThrowsAdvice(code = 31010136, print = "管理端查询考生列表失败")
    @GetMapping(value = "/list")
    public ApiResponse<Object> queryPage(StudentParam param, PageParam<StudentVo> pageParam) {
        IPage<StudentVo> page = pageParam;
        List<String> permissionList = getPermissionList(param.getProjectId());
        List<StudentVo> list = iStudentInfoService.queryStudentList(param, permissionList, page.getCurrent(), page.getSize());
        page.setTotal(iStudentInfoService.queryStudentListCount(param, permissionList));
        page.setRecords(list);
        return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data(page).build();
    }

    @Deprecated
    @ApiOperation(value = "8.1.5 导出科目考生列表", notes = "20000:成功", produces = "application/octet-stream")
    @ApiOperationSort(value = 5)
    @ThrowsAdvice(code = 31010167, print = "导出科目考生列表异常")
    @GetMapping(value = "/export")
    public ApiResponse<Object> export(StudentParam param, HttpServletResponse response) {
        if (null == param || StringUtils.isEmpty(param.getProjectId())) {
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_31010167).data("参数缺失").build();
        }
        List<String> permissionList = getPermissionList(param.getProjectId());
        iStudentInfoService.zip(response, permissionList, param);
        return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data("导出成功！").build();

    }

    @ApiOperation(value = "8.1.6 上传考生照片（上传MultipartFile）", notes = "返回文件路径:14001:成功 15020:失败,")
    @ApiOperationSort(value = 6)
    @Log(module = "考生基础信息管理", business = "上传考生照片")
    @ThrowsAdvice(code = 31010168, print = "上传考生照片异常")
    @PostMapping(value = "/uploadPhoto", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ApiResponse<Object> uploadFile(@RequestPart(value = "file") MultipartFile file, String projectCollectInfoId) throws IOException {
        String validateResult = iStudentInfoService.uploadFile(file, projectCollectInfoId);
        log.info("uploadFile projectCollectInfoId：{}, validateResult:{}", projectCollectInfoId, validateResult);
        if (StringUtils.isBlank(validateResult)) {
            String pathString = fileClient.uploadFile(file);
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data(pathString).build();
        } else {
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_31010168).data(validateResult).build();
        }
    }


    @ApiOperation(value = "8.1.7 根据项目id查询考生", notes = "14001:成功，15025:查询考生数据异常")
    @ApiOperationSort(value = 7)
    @ThrowsAdvice(code = 31081701, print = "查询考生数据失败")
    @GetMapping(value = "/queryStudentInfo")
    public ApiResponse<Object> queryStudentInfo(String projectId) {
        List<String> permissionList = getPermissionList(projectId);
        List<StudentSubject> list = iStudentSubjectService.queryStudentSubject(null, null, null, null, permissionList, projectId);
        if (CollectionUtils.isNotEmpty(list)) {
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data(false).build();
        } else {
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data(true).build();
        }
    }


    @ApiOperation(value = "8.1.9 上传附件（上传MultipartFile）", notes = "返回文件路径:14001:成功 15036:失败,")
    @ApiOperationSort(value = 9)
    @ThrowsAdvice(code = 31081901, print = "上传附件失败")
    @Log(module = "考生基础信息管理", business = "上传附件")
    @RequestMapping(value = "/uploadEnclosureFile", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ApiResponse<Object> uploadEnclosureFile(@RequestPart(value = "file") MultipartFile file, String projectCollectInfoId) throws IOException {
        // 判断附件是否合格
        String string = iStudentInfoService.uploadEnclosureFile(file, projectCollectInfoId);
        if ("".equals(string)) {
            String pathString = fileClient.uploadFile(file);
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_SUCCESS).data(pathString).build();
        } else {
            return ApiResponse.builder().code(Constant.RESPONSE_CODE_31010168).data(string).build();
        }
    }

    /**
     * 导入考生信息
     *
     * @param file
     * @return result
     */
    @ApiOperation(value = "8.1.10 导入考生信息", notes = "20000:成功 data{total: 总进度, current: 当前进度}")
    @ApiOperationSort(value = 10)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "projectId", value = "报名项目id", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "createFlag", value = "是否创建账号", dataType = "boolean", paramType = "query")
    })
    @ApiVersion(group = {ApiVersionConstant.V2_4_10})
    @Log(module = "考生基础信息管理", business = "导入考生信息")
    @PostMapping(value = "/importMulFile")
    @ProgressAnno(total = 100, timeoutSeconds = 60 * 60 * 2, errorCode = Constant.RESPONSE_CODE_31010123, canConcurrent = false, lockKeyCreator = ImportStudentLockKeyCreator.class)
    public void importMulFile(MultipartFile file, String projectId, Boolean createFlag) {
        log.info("[导入考生信息]请求参数日志 importMulFile start projectId={}", projectId);
        if (Objects.isNull(file)) {
            ProgressManager.updateProgressFailMessage(Constant.RESPONSE_CODE_31010123, "文件内容为空！");
            return;
        }
        String fileType = KqStringUtils.getFilenameExtension(file.getOriginalFilename());
        if (!("xls".equals(fileType) || "xlsx".equals(fileType))) {
            ProgressManager.updateProgressFailMessage(Constant.RESPONSE_CODE_31010123, "文件格式不正确，仅支持xls或者xlsx文件格式，请重新导入！");
            return;
        }
        String officeid = getOfficeId();
        String userId = getUserId();
        User user = getUser();
        try {
            if (null == createFlag) {
                createFlag = Boolean.FALSE;
            }
            iStudentInfoService.importMulFile(file, officeid, projectId, createFlag, user);
        } finally {
            ThreadLocalProvider.remove();
        }
    }

    /**
     * 生成账号
     *
     * @param vo
     * @return result
     */
    @ApiOperation(value = "8.1.11 生成账号", notes = "14001:成功")
    @ApiOperationSort(value = 11)
    @ThrowsAdvice(code = 31010169, print = "生成账号异常")
    @Log(module = "考生基础信息管理", business = "生成账号")
    @PostMapping(value = "/createUser")
    public ApiResponse<Object> createUser(@RequestBody ImportStudentVo vo) {
        return iStudentInfoService.createUser(getOfficeId(), vo);
    }

    @ApiOperation(value = "8.1.13 查看考生基础信息数据(V2.3.12)", notes = "20000:成功；31010136：未查找到考生基础信息数据", response = ProjectCollectInfoVo.class, responseContainer = "List")
    @ApiOperationSort(value = 13)
    @ThrowsAdvice(code = 31010198, print = "查看考生基础信息数据失败")
    @RequestMapping(value = {"/newQuery/{projectId}/{studentId}", "/newQuery/{projectId}"}, method = RequestMethod.GET)
    public ApiResponse<Object> newQuery(@PathVariable String projectId, @PathVariable(required = false) String studentId) throws Exception {
        return iStudentInfoService.newQuery(projectId, studentId);
    }

    @ApiOperation(value = "8.2.1 集体报名手动录入")
    @ApiOperationSort(value = 14)
    @AvoidReSubmit
    @ApiVersion(group = BmApiVersionConstant.V2_4_11)
    @ThrowsAdvice(code = 31082101, print = "集体报名手动录入异常")
    @Log(module = "报名集体报名管理", business = "集体报名手动录入")
    @PostMapping(value = "/batchImportManual")
    public ApiResponse<String> batchImportManual(@Validated @RequestBody BatchImportManualParam param, BindingResult bindingResult) {
        this.checkValid(bindingResult);
        // 判断手机+邮箱是否重复
        iStudentInfoService.batchImportManualDataCheck(param);

        String studentId = iStudentInfoService.batchImportManual(param.getProjectId(), param.getList(), param.getCreateFlag(), param.getSubjectIds());
        return ApiResponse.<String>builder()
                .code(Constant.RESPONSE_CODE_SUCCESS)
                .data(studentId).build();
    }

    @ApiOperation(value = "8.2.2 集体报名文件录入", response = BatchSaveImportDataVO.class)
    @ApiOperationSort(value = 15)
    @ApiVersion(group = BmApiVersionConstant.V2_4_11)
    @ProgressAnno(timeoutSeconds = 10 * 60, errorCode = 31082201, canConcurrent = false, lockKeyCreator = BatchImportFileLockKeyCreator.class)
    @Log(module = "报名集体报名管理", business = "集体报名文件录入")
    @PostMapping(value = "/batchImportFile")
    public void batchImportFile(@Validated @RequestBody BatchImportFileParam param, BindingResult bindingResult) {
        this.checkValid(bindingResult);

        iStudentInfoService.batchImportFile(param.getProjectId(), param.getFileUrl(), param.getCreateFlag(), getUser());
    }

    @ApiOperation(value = "8.2.3 集体报名模板下载", response = String.class)
    @ApiOperationSort(value = 16)
    @ApiVersion(group = BmApiVersionConstant.V2_4_11)
    @ThrowsAdvice(code = 31082301, print = "集体报名模板下载失败")
    @Log(module = "报名集体报名管理", business = "集体报名模板下载")
    @PostMapping(value = "/batchImportTemplate")
    public ApiResponse<String> batchImportTemplate(@RequestParam String projectId) {
        return ApiResponse.<String>builder()
                .code(Constant.RESPONSE_CODE_SUCCESS)
                .data(iStudentInfoService.batchImportTemplate(projectId))
                .build();
    }
    
    @ApiOperation(value = "8.3.1 福建执法同步考生", response = FjzfSyncStudentDto.class)
    @ApiOperationSort(value = 16)
    @ApiVersion(group = BmApiVersionConstant.V2_4_p18)
    @ThrowsAdvice(code = 31083101, print = "同步福建福建执法考生信息失败")
    @PostMapping(value = "/syncFjzfStudentInfo")
    public ApiResponse<FjzfSyncStudentDto> syncFjzfStudentInfo(@RequestBody FjzfSyncStudentDto fjzfSyncStudentDto)  {
        log.info("# syncFjzfStudentInfo fjzfSyncStudentDto:{}", FastJsonUtil.getBeanToJson(fjzfSyncStudentDto));
        return ApiResponse.<FjzfSyncStudentDto>builder()
                .code(Constant.RESPONSE_CODE_SUCCESS)
                .data(iStudentInfoService.syncFjzfStudentInfo(fjzfSyncStudentDto))
                .build();
    }
}
